
# flashcard.py
# this is the class for each card.

import sys
import string
import exceptions
from PyQt4 import QtGui, QtCore
from wordtype import *

class FileFormatError(exceptions.Exception):
    def __init__(self, message = 'The file is not correctly formatted!'):
        self.message = message
        return


def flashCardFromCSV(vocab, parent, values):
    if len(values) == 0:
        raise FileFormatError('No card data')
    wordtype = values.pop(0)
    if wordtype == '':
        raise FileFormatError('Empty word type!')
    # make sure that values is the right length
    length = len(vocab.wordtypes[wordtype].fields)
    #print wordtype, length
    while len(values) < length:
        values.append('')
    while len(values) > length:
        values.pop()
    return FlashCard(vocab, parent, wordtype, valuesToDict(values, vocab.wordtypes[wordtype].fields))

#def copyFlashCard(card):
#    return FlashCard(card.vocab, card.parent, card.wordType.name, card.values)

def valuesToDict(values, fields):
    # change array of values for a card into a dictionary
    # with fieldnames as keys
    # values must be the right amount in the right order
    assert(len(fields) == len(values))
    valuesDict = {}
    for i in range(len(fields)):
        valuesDict[fields[i].name] = values[i]
    return valuesDict

class FlashCard(QtGui.QWidget):
        
    def __init__(self, vocab, parent, wordtype, values):
        QtGui.QWidget.__init__(self, parent)
        
        self.parent = parent
        self.vocab = vocab
        self.wordType = self.vocab.wordtypes[wordtype]
        self.values = values
        # make sure there's a value for each field
        for field in self.wordType.fields:
            if not field.name in self.values:
                self.values[field.name] = ''
        assert(len(self.values) >= len(self.wordType.fields))
        self.fieldInstances = {}
        self.fieldIndices = {}
        self.guiArea = {}
        
        self.mainLayout = QtGui.QGridLayout(self)
    
    def doLayout(self):
        if not len(self.guiArea) > 0: # if we have already done the layout don't do it again
            #self.mainLayout = QtGui.QGridLayout()
            self.guiArea[FieldPosition.LEFT] = QtGui.QVBoxLayout()
            self.guiArea[FieldPosition.RIGHT] = QtGui.QVBoxLayout()
            self.guiArea[FieldPosition.CENTRE] = QtGui.QVBoxLayout()
        
            homePreString = ''
            foreignPreString = ''
            homePostString = ''
            foreignPostString = ''
            for i in range(len(self.wordType.fields)):
                fieldName = self.wordType.fields[i].name
                if not fieldName in self.values.keys():
                    self.values[fieldName] = ''
                if self.wordType.fields[i].position == FieldPosition.PREFIX:
                    #if str(self.wordType.fields[i].font.family()) == str(self.vocab.fontName):
                        foreignPreString = foreignPreString + self.values[fieldName] + ' '
                    #else:
                    #    homePreString = homePreString + self.values[fieldName] + ' '
                elif self.wordType.fields[i].position == FieldPosition.POSTFIX:
                   # if self.wordType.fields[i].font.family().compare(self.vocab.foreignFontBig.family()) == 0:
                        foreignPostString = foreignPostString + ' ' + self.values[fieldName]
                    #else:
                    #    homePostString = homePostString + ' ' + self.values[fieldName]
                else:
                    self.fieldIndices[fieldName] = i
                    if fieldName != 'english' and fieldName != 'foreign':
                        fieldInst = self.wordType.fields[i].instantiate(self.values[fieldName], self)
                        self.fieldInstances[fieldName] = fieldInst
                        self.guiArea[fieldInst.field.position].insertLayout(-1, fieldInst.layout)
            englishFull = homePreString + self.values['english'] + homePostString
            self.fieldInstances['english'] = self.wordType.fields[self.fieldIndices['english']].instantiate(englishFull, self)
            self.guiArea[FieldPosition.CENTRE].insertLayout(0, self.fieldInstances['english'].layout)
            foreignFull = foreignPreString + self.values['foreign'] + foreignPostString
            self.fieldInstances['foreign'] = self.wordType.fields[self.fieldIndices['foreign']].instantiate(foreignFull, self)
            self.guiArea[FieldPosition.CENTRE].insertLayout(0, self.fieldInstances['foreign'].layout)
        
            self.mainLayout.addLayout(self.guiArea[FieldPosition.LEFT], 0, 0, QtCore.Qt.AlignLeft)
            self.mainLayout.addLayout(self.guiArea[FieldPosition.RIGHT], 0, 1, QtCore.Qt.AlignRight)
            self.mainLayout.addLayout(self.guiArea[FieldPosition.CENTRE], 1, 0, 1, -1, QtCore.Qt.AlignCenter)
            #self.setLayout(self.mainLayout)
        
        self.reset()
    
    def redoLayout(self):
        if len(self.guiArea) > 0:
            for field in self.fieldInstances:
                self.fieldInstances[field].layout.setParent(None)
                self.fieldInstances[field].setVisible(False)
            for key in self.guiArea:
                self.guiArea[key].setParent(None)
            del self.fieldInstances
            del self.fieldIndices
            del self.guiArea
            self.fieldInstances = {}
            self.fieldIndices = {}
            self.guiArea = {}
            #self.setLayout(None)
            #self.mainLayout = None
        self.doLayout()
    
    def show(self, visible, fieldType):
        for key in self.fieldInstances:
            if self.fieldInstances[key].field.show == fieldType and self.fieldInstances[key].field.position != FieldPosition.PREFIX and self.fieldInstances[key].field.position != FieldPosition.POSTFIX:
                self.fieldInstances[key].setVisible(visible)
    
    def reset(self):
        self.show(True, FieldShow.ALWAYS)
        self.show(False, FieldShow.ONHINT)
        self.show(False, FieldShow.ONREVEAL)
        self.show(False, FieldShow.NEVER)
    
    def refreshFonts(self):
        if len(self.guiArea) > 0:
            for field in self.fieldInstances:
                self.fieldInstances[field].refreshFont()
    
    def changeDifficulty(self, inc):
        self.values['difficulty'] = str(float(self.values['difficulty']) + inc)
        self.fieldInstances['difficulty'].setValue(str(self.values['difficulty']))
        self.vocab.changed = True
    
    def toCSV(self, csvWriter):
        """write CSV that defines this card"""
        row = [self.wordType.name]
        # The order of values must be the same as the order of fields in the list of fields in the wordtype object
        # as this is how values are matched to fields when the card is read from csv
        for i in range(len(self.wordType.fields)):
            if self.wordType.fields[i].name in self.values.keys():
                row.append((self.values[self.wordType.fields[i].name]))
            else:
                row.append('')
        csvWriter.writerow(row)
    
    def writeXML(self, xmlWriter):
        """write XML that defines this card"""
        xmlWriter.writeStartElement('flashCard')
        xmlWriter.writeAttribute('type', self.wordType.name)
        # only save values that belong to a field
        for field in self.wordType.fields:
            # don't bother saving empty values
            if str(field.name) in self.values and (not self.values[str(field.name)] == ''):
                xmlWriter.writeTextElement(field.name, self.values[str(field.name)])
        xmlWriter.writeEndElement()
    
    def copy(self):
        valuesCopy = {}
        for key in self.values:
            valuesCopy[key] = self.values[key]
        return FlashCard(self.vocab, self.parent, self.wordType.name, valuesCopy)

